package com.carbon.domain.common;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.carbon.domain.common.ApiCode;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Date;

@Data
@Accessors(chain = true)
@AllArgsConstructor
public class ApiResult<T> implements Serializable {

    private int code;
    private T data;
    private String msg;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date time;


    public static <T> ApiResult<T> result(int code, String msg, T data) {
        return new ApiResult<>(code, data, msg, DateUtil.date());
    }

    public static <T> ApiResult<T> result(ApiCode apiCode, String msg, T data) {
        String message = apiCode.getMsg();
        if (StrUtil.isNotBlank(msg)) {
            message = msg;
        }
        return new ApiResult<>(apiCode.getCode(), data, message, DateUtil.date());
    }

    public static <T> ApiResult<T> result(ApiCode apiCode, T data) {
        return result(apiCode, null, data);
    }


    // 1. 带ApiCode、自定义消息、数据
    public static <T> ApiResult<T> ok(ApiCode apiCode, String msg, T data) {
        return result(apiCode, msg, data);
    }

    // 2. 带ApiCode、自定义消息（无数据）
    public static <T> ApiResult<T> ok(ApiCode apiCode, String msg) {
        return ok(apiCode, msg, null); // 内部传null，避免调用者传null导致类型问题
    }

    // 3. 带ApiCode、数据（用枚举默认消息）
    public static <T> ApiResult<T> ok(ApiCode apiCode, T data) {

        return ok(apiCode, apiCode.getMsg(), data);
    }

    // 4. 仅带自定义消息（用默认成功码ApiCode.SUCCESS）
    public static <T> ApiResult<T> ok(String msg) {

        return result(ApiCode.SUCCESS, msg, null);
    }

    // 5. 带数据和默认消息（用默认成功码）
    public static <T> ApiResult<T> ok(T data) {
        return result(ApiCode.SUCCESS, ApiCode.SUCCESS.getMsg(), data);
    }

    // 6. 无参数（默认成功码+默认消息）
    public static <T> ApiResult<T> ok() {
        return ok(null); // 调用上面的ok(T data)，此时data为null
    }


    public static <T> ApiResult<T> fail(ApiCode apiCode) {
        return result(apiCode, null);
    }

    public static <T> ApiResult<T> fail(ApiCode apiCode, String msg) {
        return result(apiCode, msg, null);
    }

    public static <T> ApiResult<T> fail(String msg) {
        return result(ApiCode.FAIL, msg, null);
    }

    public static <T> ApiResult<T> result(boolean flag, T data) {
        if (flag) {
            return ok(data);
        }
        return fail("");
    }

    public static <T> ApiResult<T> result(boolean flag) {
        if (flag) {
            return ok();
        }
        return fail("");
    }

    public static <T> ApiResult<T> result(ApiCode apiCode) {
        return result(apiCode, null);
    }
}